refactor ForEachFunction to use the existing registry instead of crea…#419
refactor ForEachFunction to use the existing registry instead of crea…#419oscar-penelo wants to merge 16 commits into
Conversation
Walkthroughfor_each now reuses the shared JsonWidgetRegistry by namespacing per-item keys and replacing identifiers only outside string literals. DeferredJsonWidgetData accepts a dynamic key and optional onResolved cleanup callback and resolves via JsonWidgetData.fromDynamic(...). Package version bumped to 12.0.1; example Issue420 added. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant ForEach as for_each
participant Registry as JsonWidgetRegistry
participant Template as Template JSON
participant Decoder as JSON→JsonWidgetData
participant Deferred as DeferredJsonWidgetData
Note over ForEach,Registry: New flow — reuse shared registry and namespace per-item keys
ForEach->>Registry: generate uniqueSuffix
loop for each item
ForEach->>Registry: set(compositeValueKey, itemValue)
ForEach->>Registry: set(compositeIndexKey, indexOrKey)
ForEach->>Template: replace identifiers outside string literals with composite keys
Template->>Decoder: decode replaced JSON
Decoder->>Deferred: create DeferredJsonWidgetData(decoded, registry=Registry, onResolved=cleanup)
ForEach->>Deferred: collect deferred widget
end
Deferred->>Registry: onResolved callback triggers cleanup of namespaced keys
sequenceDiagram
autonumber
participant ForEachOld as for_each (old)
participant RegistryOld as JsonWidgetRegistry (per-item)
participant TemplateOld as Template JSON
participant DecoderOld as JSON→JsonWidgetData
participant DeferredOld as DeferredJsonWidgetData
Note over ForEachOld,RegistryOld: Old flow — created per-item registries
loop for each item
ForEachOld->>RegistryOld: create new JsonWidgetRegistry()
ForEachOld->>RegistryOld: set("value", itemValue)
ForEachOld->>TemplateOld: replace placeholders referencing "value"
TemplateOld->>DecoderOld: decode replaced JSON
DecoderOld->>DeferredOld: create DeferredJsonWidgetData(decoded, registry=RegistryOld)
ForEachOld->>DeferredOld: collect deferred widget
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
✏️ Tip: You can disable this entire section by setting Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
packages/json_dynamic_widget/CHANGELOG.md(1 hunks)packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(1 hunks)packages/json_dynamic_widget/pubspec.yaml(1 hunks)
🔇 Additional comments (2)
packages/json_dynamic_widget/pubspec.yaml (1)
4-4: LGTM!The patch version bump to 12.0.1 is appropriate for this refactoring change.
packages/json_dynamic_widget/CHANGELOG.md (1)
1-4: LGTM!The changelog entry clearly documents the registry reuse change and its impact on variable scope during iteration.
… the 'global' registry for each item
There was a problem hiding this comment.
Actionable comments posted: 2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
examples/json_dynamic_widget_example/lib/src/issue_420_page.dart(1 hunks)examples/json_dynamic_widget_example/lib/src/launcher.dart(2 hunks)packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(3 hunks)packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart(2 hunks)
🔇 Additional comments (2)
examples/json_dynamic_widget_example/lib/src/launcher.dart (1)
17-18: Issue420Page wiring matches existing patternsThe new import and
'issue_420'route follow the same pattern as other issue pages and are consistent with how the example navigator is structured.Also applies to: 262-266
packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart (1)
8-15: The review's primary concern about breaking changes is unsupported by actual usage patterns.Verification shows:
String key risk is invalid: All actual calls to
DeferredJsonWidgetData(infor_each.dartat lines 81 and 119) passjson.decode(replacedTemplate)— fully decoded JSON objects, not string variable names. The change aligns with existing usage.Optimization suggestion is valid:
JsonWidgetData.fromDynamic()does accept aregistryparameter (confirmed injson_widget_data.dart), so the suggestion to avoidcopyWithis technically sound but optional—both approaches work.Properly scoped:
DeferredJsonWidgetDatais internal-only for deferred widget parsing. The semantic change is intentional and supported by actual call sites.The core risk assessment is unfounded. The code change is correct as written.
Likely an incorrect or invalid review comment.
…g and maintainability
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (3)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (3)
7-8: Unique key generation is reasonable; implementation looks goodUsing a shared
_randomand_random10Digits()to generate a per‑invocationuniqueKeyis a simple and effective way to namespace per‑item variables and avoid the previous “last iteration wins” issue. Collision probability with 10 random digits is negligible for typical usage, so this looks fine as implemented.If you ever expect extremely high volumes or long‑lived registries, you could document the collision assumptions or switch to something like an incrementing counter/UUID, but it’s not strictly necessary here.
Also applies to: 20-26, 32-32
34-37: Remove unusedtemplatelocal for clarity
final template = '\${${args[1]}}';is no longer used now that you work directly fromtemplateObjectString. Keeping it around is slightly confusing and may mislead future readers about how the template is resolved.You can safely drop it:
- final template = '\${${args[1]}}'; - final templateObjectString = json.encode(registry.getValue(args[1])); + final templateObjectString = json.encode( + registry.getValue(args[1]), + );
47-102: Placeholder rewriting strategy is sound; apply optional DRY/perf improvementsThe overall approach correctly avoids the "shared mutable state" bug by using per-item names like
value_<uniqueKey>_<index>/key_<uniqueKey>_<index>, and restricting replacements to${…}and whole-wordvarName/keyNameoccurrences. Registry keys are treated as opaque strings with no path parsing, so special characters in Map keys pose no structural risks.Consider these micro-optimizations in both branches (lines 47–102 and 104–153):
placeholderPatternis identical and recomputed per iteration; hoist tostatic finalor compute once per_bodycall.varNamePattern/keyNamePatterndepend only onvarName/keyName, not on the index orentry.key; compute once per branch and reuse inside the callback to avoid per-item regex allocations.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
examples/json_dynamic_widget_example/lib/src/issue_420_page.dart(1 hunks)packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- examples/json_dynamic_widget_example/lib/src/issue_420_page.dart
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (1)
114-116: Remove redundant regex creation.The
keyNamePatternis already created at line 46 and can be reused here. Recreating it on each map iteration is inefficient and unnecessary.Apply this diff to use the existing pattern:
inside = inside.replaceAllMapped( varNamePattern, (_) => '${varName}_${uniqueKey}_${entry.key}', ); - final keyNamePattern = RegExp( - r'\b' + RegExp.escape(keyName) + r'\b', - ); inside = inside.replaceAllMapped( keyNamePattern, (_) => '${keyName}_${uniqueKey}_${entry.key}', );
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
examples/json_dynamic_widget_example/lib/src/issue_420_page.dart(1 hunks)packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(3 hunks)
🔇 Additional comments (3)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (2)
1-2: LGTM: Imports support the unique key generation strategy.The addition of
dart:convertanddart:mathalong with the global_randominstance appropriately supports the new approach of generating unique keys for per-item registry values.Also applies to: 7-7
48-90: LGTM: Iterable branch correctly implements scoped replacement strategy.The implementation properly:
- Stores per-item values in the shared registry with unique keys
- Scopes variable/key name replacements to placeholder expressions only (via
placeholderPattern), preventing corruption of property names- Creates deferred widgets that reference the correct registry values via the modified template
This addresses the concerns from previous reviews about both registry state capture and overly broad replacements.
examples/json_dynamic_widget_example/lib/src/issue_420_page.dart (1)
1-54: LGTM: Example effectively demonstrates the registry sharing behavior.This example appropriately exercises the refactored
for_eachfunctionality:
- The
for_each(array, 'template')call renders multiple buttons using shared registry- Each button's
onPressedupdates the parent context'smyvaluevariable viaset_value- The listening text widget reflects these changes, confirming that variables set during iteration are now accessible in the broader context
This serves as both a regression test and documentation for issue 420.
There was a problem hiding this comment.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(3 hunks)packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart(4 hunks)
🔇 Additional comments (9)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (5)
17-23: LGTM: Unique key generation eliminates collision risk.The combination of microsecond timestamp and incrementing counter provides a robust unique identifier for each
for_eachinvocation, effectively addressing the collision concerns from previous reviews.
25-32: LGTM: Cleanup function is straightforward.The helper correctly removes per-item registry keys, preventing memory leaks from accumulated iteration variables.
50-52: LGTM: Efficient regex pattern creation.The patterns are correctly created once per invocation rather than per iteration, and the use of
RegExp.escape()ensures special characters in variable names are handled safely.
73-89: LGTM: Template replacement approach is pragmatic and safe.The current implementation correctly limits replacement to within
${...}placeholders only, avoiding the broader string-wide corruption issues flagged in earlier reviews. The word-boundary regex (\b) properly isolates variable names in most expression contexts.Note: Theoretical edge case exists where variable names appear in string literals within expressions (e.g.,
${"text with value in it" + value}), but this would require full expression parsing and is unlikely in typical usage.
91-100: LGTM: Cleanup callback correctly tied to widget lifecycle.The
onResolvedcallback ensures per-item registry values are removed when the deferred widget is disposed, completing the cleanup strategy and preventing memory leaks.packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart (4)
8-18: LGTM: Constructor changes enable flexible key types and cleanup.The change from
Stringtodynamickey type accommodates the new template replacement approach infor_each, and the optionalonResolvedcallback provides the hook needed for registry cleanup.
33-35: LGTM: Data resolution correctly handles dynamic keys.Using
JsonWidgetData.fromDynamic()properly handles the dynamic key type introduced by the template replacement mechanism infor_each.
52-78: LGTM: Build method correctly implements cleanup lifecycle.The conditional wrapping strategy is well-designed:
- Returns the built widget directly when cleanup is not needed
- Handles the
PreferredSizeWidgetspecial case to preserve its interface- Wraps in a cleanup widget that invokes
onResolvedon disposalThis ensures registry values are cleaned up when the widget is removed from the tree.
111-163: LGTM: Cleanup widget implementations follow standard Flutter patterns.Both
_CleanupWidgetand_PreferredSizeCleanupWidgetare implemented correctly:
- Stateful widgets that invoke callbacks in
dispose()- Simple pass-through rendering that forwards the child
_PreferredSizeCleanupWidgetcorrectly implementsPreferredSizeWidgetinterface
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (1)
53-143: Logic is sound; consider extracting shared iteration logic.The implementation correctly:
- Generates unique per-item keys scoped by the invocation
- Stores values in the shared registry with proper namespacing
- Replaces identifiers safely within placeholder expressions
- Sets up cleanup callbacks to prevent memory leaks
Both the Iterable and Map branches follow the same pattern with only minor variations (index vs. entry.key). While the current duplication is localized and manageable, extracting a helper function for the shared logic could improve maintainability.
Optional refactor to reduce duplication:
Consider extracting the common pattern into a helper:
static JsonWidgetData _createDeferredWidget({ required String valueKey, required String keyKey, required dynamic value, required dynamic key, required String templateObjectString, required String varName, required String keyName, required RegExp placeholderPattern, required JsonWidgetRegistry registry, }) { registry.setValue(valueKey, value, originator: null); registry.setValue(keyKey, key, originator: null); final replacedTemplate = templateObjectString.replaceAllMapped( placeholderPattern, (match) { var inside = match.group(1)!; inside = _replaceIdentifiersOutsideStringLiterals( inside, {varName: valueKey, keyName: keyKey}, ); return '\${$inside}'; }, ); return DeferredJsonWidgetData( key: json.decode(replacedTemplate), registry: registry, onResolved: () => _cleanupRegistryValues(registry, [valueKey, keyKey]), ); }Then both branches would simplify to:
// Iterable branch results.add(_createDeferredWidget( valueKey: '${varName}_${uniqueKey}_$index', keyKey: '${keyName}_${uniqueKey}_$index', value: value, key: index, // ... other params )); // Map branch results.add(_createDeferredWidget( valueKey: '${varName}_${uniqueKey}_${entry.key}', keyKey: '${keyName}_${uniqueKey}_${entry.key}', value: entry.value, key: entry.key, // ... other params ));
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
examples/json_dynamic_widget_example/lib/src/issue_420_page.dart(1 hunks)packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- examples/json_dynamic_widget_example/lib/src/issue_420_page.dart
🔇 Additional comments (4)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (4)
1-18: Clean setup with appropriate dependencies.The addition of
dart:convertfor JSON manipulation and the static members for unique key generation are well-structured. The use of a static counter is safe in Dart's single-threaded execution model for typical use cases.
20-24: Excellent unique key generation strategy.Combining timestamp with an incrementing counter provides strong uniqueness guarantees while keeping keys compact via base-36 encoding. This effectively eliminates the collision risk present in random-only approaches.
26-33: LGTM: Proper cleanup mechanism.The cleanup function correctly removes per-item registry entries, preventing memory leaks in long-running applications. This relies on the
onResolvedcallback being invoked byDeferredJsonWidgetData, which was confirmed in previous review iterations.
149-217: Robust identifier replacement with proper quote handling.This method correctly addresses the previous concern about corrupting string literals by:
- Tracking when the parser is inside quoted strings (single or double quotes)
- Properly handling escaped quotes through backslash counting (even count = unescaped)
- Only replacing identifiers outside strings and at word boundaries
- Supporting multiple simultaneous replacements
The character-by-character approach is necessary for correctness and the performance trade-off is acceptable for typical template sizes.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (1)
91-91: Optional: Note limitation with nested braces in expressions.The placeholder pattern
r'\$\{([^}]*)\}'uses[^}]*which captures content until the first}character. This means expressions with nested braces (e.g.,${someFunction({key: value})}) would be incorrectly parsed, as the capture would stop at the first closing brace.However, this is likely an acceptable limitation since:
- Such complex expressions may not be supported by the library's expression parser anyway
- The current pattern handles all examples and typical use cases correctly
- Fixing this would require a more complex parser (bracket matching/counting)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(3 hunks)packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart(4 hunks)
🔇 Additional comments (2)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (1)
1-209: Excellent refactor addressing the registry sharing issue!The solution is well-designed and correctly fixes the original problem. The approach of using unique per-item keys with the shared registry, combined with the cleanup mechanism, ensures that:
- Actions inside templates can interact with the global registry (fixing issue #420)
- Each iteration maintains its own variable scope via unique keys
- Registry entries are properly cleaned up when widgets are disposed
- All past review concerns (collisions, string replacement, cleanup) have been addressed
The
_replaceIdentifiersOutsideStringLiteralsfunction is particularly well-implemented with correct handling of quote tracking, escape sequences, and word boundaries.packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart (1)
1-164: Well-implemented cleanup mechanism with proper widget lifecycle integration.The changes cleanly support the new
for_eachdesign:
- The dynamic key type provides flexibility for passing decoded template objects
- The
onResolvedcallback enables proper registry cleanup when widgets are disposed- The cleanup wrapper widgets correctly implement the Flutter lifecycle (dispose) and handle the
PreferredSizeWidgetspecial case- The resolution path via
JsonWidgetData.fromDynamicis cleaner than the previous approachThe implementation correctly ensures that registry entries are cleaned up when widgets are removed from the tree, preventing memory leaks in normal usage scenarios.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (2)
17-17: Thread-safety consideration for the counter.The static
_uniqueKeyCounteris not synchronized, but this is acceptable for typical Flutter/Dart usage where code runs on a single isolate. If the library is used in a multi-isolate environment, consider using atomic operations or per-isolate counters to guarantee uniqueness across isolates.
203-271: LGTM! The identifier replacement logic is correct and safe.The implementation carefully:
- Only replaces outside string literals via quote state tracking
- Ensures word boundaries to avoid partial matches (e.g., won't replace "value" in "myvalue")
- Handles escaped quotes properly
The O(n × m) complexity (where m = number of replacements, typically 2) is acceptable for the expected usage patterns. If performance becomes a concern with very large templates, consider using a more efficient approach like regex compilation or a trie-based matcher.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart(3 hunks)
🔇 Additional comments (4)
packages/json_dynamic_widget/lib/src/components/functions/for_each.dart (4)
20-24: LGTM! Unique key generation eliminates collision risk.The timestamp + counter approach provides guaranteed uniqueness and addresses the previous collision concerns mentioned in past reviews.
66-127: LGTM! The registry sharing approach correctly addresses the PR objectives.The refactored logic successfully:
- Uses the shared registry instead of creating per-iteration instances, fixing the global registry access issue
- Creates unique keys per invocation and per item to prevent collisions
- Maintains iteration-specific values through namespaced registry keys
- Delegates cleanup to the deferred widget lifecycle
The approach elegantly solves the problem described in issue #420 where actions inside templates couldn't access the global registry.
129-201: LGTM! The placeholder replacement logic is robust.The implementation correctly handles complex edge cases:
- Nested
${}expressions via brace depth tracking- String literals inside expressions via quote state tracking
- Escaped quotes via backslash counting (even number of backslashes = not escaped)
- Malformed templates via early break when braces don't match
This addresses the previous review concern about broad string replacement corrupting templates by only replacing identifiers inside interpolation expressions and outside string literals.
35-64: Address potential memory leak from unusedDeferredJsonWidgetDatainstances in lazy-rendered lists.The
onResolvedcleanup callback only fires whenDeferredJsonWidgetData.build()is invoked. However, whenfor_eachresults are passed to widgets using lazy item builders (ListView, GridView, SliverList), items that never reach the viewport are never built, leaving their registry values (valueKeyandkeyKey) indefinitely orphaned.In long-running applications with large datasets (e.g., a ListView with 10,000 items where only 10 are visible), this causes unbounded registry growth and memory leaks.
Mitigation options:
- Wrap results in a lifecycle-aware container that cleans up offscreen items
- Use weak references for registry values to allow garbage collection
- Implement explicit cleanup when the parent container is disposed
- Document this limitation for users creating large
for_eachlists
|
Great report and thanks for the PR. I'll try to get to it within the week. |
|
Apologies... Vacations and travel got in the way. It looks like this now has merge conflicts. :( |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
packages/json_dynamic_widget/CHANGELOG.md (2)
1-29: Remove duplicate changelog entry and fix chronological ordering.The version
12.0.1entry appears twice (lines 1-4 and lines 26-29) with identical content. Additionally, if the date of November 15th, 2025 is correct, this entry should appear after versions dated in January 2026 (lines 6-14), not before them. CHANGELOGs should be in reverse chronological order (newest first).Please:
- Remove one of the duplicate entries
- Verify the release date and reorder entries chronologically
📝 Proposed fix assuming November 15th, 2025 date is correct
-## [12.0.1] - November 15th, 2025 - -* 'for_each' function now uses the existing registry instead of creating new instances. This ensures that variables set during iteration are accessible in the broader context and resolves issues related to variable scope during iteration. - - ## [12.0.0+5] - January 13, 2026 * Automated dependency updates
431-431: Remove git merge conflict marker.A git merge conflict marker was left in the file, indicating incomplete conflict resolution. This must be removed before merging.
🔧 Proposed fix
->>>>>>> fabcc57c6772a1015dbb260dc2cb5a28bfade292:CHANGELOG.md -
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
packages/json_dynamic_widget/CHANGELOG.mdpackages/json_dynamic_widget/pubspec.yaml
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/json_dynamic_widget/pubspec.yaml
🧰 Additional context used
🪛 markdownlint-cli2 (0.18.1)
packages/json_dynamic_widget/CHANGELOG.md
26-26: Multiple headings with the same content
(MD024, no-duplicate-heading)
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/json_dynamic_widget/CHANGELOG.md (1)
426-426: Remove the merge conflict marker.A Git merge conflict marker has been left in the file. This must be removed before merging.
🔧 Proposed fix
->>>>>>> fabcc57c6772a1015dbb260dc2cb5a28bfade292:CHANGELOG.md
🤖 Fix all issues with AI agents
In `@packages/json_dynamic_widget/CHANGELOG.md`:
- Around line 1-5: Update the release header for "## [12.0.1] - November 15th,
2025" in packages/json_dynamic_widget/CHANGELOG.md to the correct release date
in January 2026 (e.g., "## [12.0.1] - January 15th, 2026") so the 12.0.1 entry
is chronologically after "12.0.0+5" dated January 13, 2026; edit that exact
header line to reflect the correct date.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/json_dynamic_widget/CHANGELOG.md
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
|
Hi @jpeiffer , all Changelog conflicts are solved. You can merge it 😄 |
Fixes #420
Description
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyzeordart analyze) does not report any problems on my PR.pubspec.yamlwith an appropriate new version according to the pub versioning philosophy.CHANGELOG.mdto add a description of the change.UI Change
Does your PR affect any UI screens?
Summary by CodeRabbit
Bug Fixes
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.